package com.xiguaji.tiktok.v1.ins.blogger.service;

import cn.hutool.core.date.DateUtil;
import com.xiguaji.boot.toolkit.DateTimeUtils;
import com.xiguaji.boot.toolkit.elasticsearch.RestClientHelper;
import com.xiguaji.boot.toolkit.jdbc.Page;
import com.xiguaji.tiktok.utils.ESUtil;
import com.xiguaji.tiktok.v1.ins.blogger.dto.*;
import com.xiguaji.tiktok.v1.ins.blogger.dto.es.InsBlogger;
import com.xiguaji.tiktok.v1.ins.blogger.model.InsMarkBloggerDay;
import com.xiguaji.tiktok.v1.ins.blogger.repository.InsBloggerRepository;
import com.xiguaji.tiktok.v1.ins.blogger.repository.InsMarkBloggerDayRepository;
import com.xiguaji.tiktok.v1.ins.config.InsConfig;
import com.xiguaji.tiktok.v1.ins.dic.model.InsDicGeneration;
import com.xiguaji.tiktok.v1.ins.dic.service.DicService;
import lombok.val;
import org.apache.lucene.search.join.ScoreMode;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class InsBloggerService {

    int [] genders = new int[]{3,2,1};

    int [] followers = new int[]{1,5,10,50,100,500,1000};
    int [] ers = new int[]{1,3,5,10,20,30};
    int [] followerGrowths = new int[]{5,10,20,30,50};
    String [] audienceGenders = new String[]{"MALE","FEMALE"};
    private final int [] DAY_TYPE = new int[]{7,15,30};

    List<InsDicGeneration> ages;

    @Autowired
    DicService dicService;

    /**
     * insMediaRepository
     */
    @Autowired
    InsMarkBloggerDayRepository insMarkBloggerDayRepository;

    /**
     * insBloggerRepository
     */
    @Autowired
    InsBloggerRepository insBloggerRepository;

    /**
     * insConfig
     */
    @Autowired
    InsConfig insConfig;

    private final int BLOGGER_TOTAL_SIZE = 1000;

    @PostConstruct
    public void init(){
        ages = dicService.getDicGenerationByType(1);
    }


    public Page<InsBlogger> getPageByEs(InsBloggerSearchData searchData){
        /*SearchRequest searchRequest = new SearchRequest(ESUtil.INS_BLOGGER_INDEX);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();*/
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
        boolQueryBuilder.must(QueryBuilders.existsQuery("username"));

        if(!StringUtils.isEmpty(searchData.getUsername())){
            boolQueryBuilder.must(QueryBuilders.wildcardQuery("username","*"+searchData.getUsername()+"*"));
        }

        //分类
        if(!StringUtils.isEmpty(searchData.getPrimaryCategory())){
            boolQueryBuilder.must(QueryBuilders.wildcardQuery("overallCategoryName",searchData.getPrimaryCategory()));
        }
        if(!StringUtils.isEmpty(searchData.getSecondCategory())){
            boolQueryBuilder.must(QueryBuilders.wildcardQuery("categoryName",searchData.getSecondCategory()));
        }


        // 提及的用户
        if(!StringUtils.isEmpty(searchData.getTaggedUsername())){
            boolQueryBuilder.must(QueryBuilders.nestedQuery("taggedBrand",QueryBuilders.matchQuery("taggedBrand.username",searchData.getTaggedUsername()), ScoreMode.Total));
        }

        //国家
        if(!StringUtils.isEmpty(searchData.getRegion())){
            boolQueryBuilder.must(QueryBuilders.matchQuery("nation",searchData.getRegion()));
        }
        //语言
        if(!StringUtils.isEmpty(searchData.getLanguage())){
            boolQueryBuilder.must(QueryBuilders.matchQuery("language",searchData.getLanguage()));
        }
        //性别
        if(searchData.getGender() > 0){
            int index = searchData.getGender()-1;

            if(index >= genders.length){
                boolQueryBuilder.must(QueryBuilders.matchQuery("gender",genders[genders.length-1]));
            }
            boolQueryBuilder.must(QueryBuilders.matchQuery("gender",genders[index]));
        }
        //年龄
        if(searchData.getAge() > 0){
            int index = searchData.getAge()-1;

            val insDicGeneration = ages.get(index);

            boolQueryBuilder.must(QueryBuilders.rangeQuery("age").gte(insDicGeneration.getGenerationStart()).lte(insDicGeneration.getGenerationEnd()));
        }
        //认证方式
        if(searchData.getVerification() > 0){
            if(searchData.getVerification() > 1){
                boolQueryBuilder.must(QueryBuilders.matchQuery("isVerified",false));
            }else {
                boolQueryBuilder.must(QueryBuilders.matchQuery("isVerified",true));
            }
        }
        //联系信息
        if(searchData.getContact() > 0){
            boolQueryBuilder.must(QueryBuilders.existsQuery("contactPhoneNumber"));
            boolQueryBuilder.must(QueryBuilders.existsQuery("publicEmail"));
            boolQueryBuilder.mustNot(QueryBuilders.termQuery("contactPhoneNumber",""));
            boolQueryBuilder.mustNot(QueryBuilders.termQuery("publicEmail",""));
        }
        //粉丝数
        if(searchData.getFollowers() > 0){
            int index = searchData.getFollowers() -1;
            if(index >= followers.length-1){
                boolQueryBuilder.must(QueryBuilders.rangeQuery("followerCount").gte(followers[followers.length-1]*10000));
            }else{
                boolQueryBuilder.must(QueryBuilders.rangeQuery("followerCount").gte(followers[index]*10000).lte(followers[index+1]*10000));
            }
        }
        //粉丝数自定义
        if(null != searchData.getFollowersDiy() && searchData.getFollowersDiy().getTo() > 0){
            boolQueryBuilder.must(QueryBuilders.rangeQuery("followerCount").gte(searchData.getFollowersDiy().getFrom()).lte(searchData.getFollowersDiy().getTo()));
        }
        //真实粉丝数
        if(searchData.getQualityFollowers() > 0){
            int index = searchData.getQualityFollowers() -1;
            if(index >= followers.length-1){
                boolQueryBuilder.must(QueryBuilders.rangeQuery("realFollowerCount").gte(followers[followers.length-1]*10000));
            }else{
                boolQueryBuilder.must(QueryBuilders.rangeQuery("realFollowerCount").gte(followers[index]*10000).lte(followers[index+1]*10000));
            }
        }
        //真实粉丝数自定义
        if(null != searchData.getQualityFollowersDiy() && searchData.getQualityFollowersDiy().getTo() > 0){
            boolQueryBuilder.must(QueryBuilders.rangeQuery("realFollowerCount").gte(searchData.getQualityFollowersDiy().getFrom()).lte(searchData.getQualityFollowersDiy().getTo()));
        }

        //广告参与率
        if(searchData.getAdEr() > 0 ){
            int index = searchData.getAdEr() -1;
            if(index >= ers.length-1){
                boolQueryBuilder.must(QueryBuilders.rangeQuery("brandMediaEr").gte(ers[ers.length-1]/100.0));
            }else{
                boolQueryBuilder.must(QueryBuilders.rangeQuery("brandMediaEr").gte(ers[index]/100.0).lte(ers[index+1]/100.0));
            }
        }

        //参与率
        if(searchData.getEr() > 0){
            int index = searchData.getEr() -1;
            if(index >= ers.length-1){
                boolQueryBuilder.must(QueryBuilders.rangeQuery("engagementRate").gte(ers[ers.length-1]/100.0));
            }else{
                boolQueryBuilder.must(QueryBuilders.rangeQuery("engagementRate").gte(ers[index]/100.0).lte(ers[index+1]/100.0));
            }
        }
        //参与率自定义
        if(null != searchData.getErDiy() && searchData.getErDiy().getTo() > 0){
            boolQueryBuilder.must(QueryBuilders.rangeQuery("engagementRate").gte(searchData.getErDiy().getFrom()/100.0).lte(searchData.getErDiy().getTo()/100.0));
        }
        //粉丝增长率
        if(searchData.getFollowerGrowth() > 0){
            int index = searchData.getFollowerGrowth() -1;
            if(index == 0){
                boolQueryBuilder.must(QueryBuilders.rangeQuery("followerGrowthRate").lt(followerGrowths[index]/100.0));
            }else if(index >= followerGrowths.length){
                boolQueryBuilder.must(QueryBuilders.rangeQuery("followerGrowthRate").gte(followerGrowths[followerGrowths.length-1]/100.0));
            }else{
                boolQueryBuilder.must(QueryBuilders.rangeQuery("followerGrowthRate").gte(followerGrowths[index-1]/100.0).lte(followerGrowths[index]/100.0));
            }
        }
        //粉丝增长率自定义
        if(null != searchData.getFollowerGrowthDiy() && searchData.getFollowerGrowthDiy().getTo() > 0) {
            boolQueryBuilder.must(QueryBuilders.rangeQuery("followerGrowthRate").gte(searchData.getFollowerGrowthDiy().getFrom()/100.0).lte(searchData.getFollowerGrowthDiy().getTo()/100.0));
        }
        //粉丝最多的国家
        if(!StringUtils.isEmpty(searchData.getAudienceRegionMore())){
            BoolQueryBuilder regionQuery = new BoolQueryBuilder();
            regionQuery.must(QueryBuilders.matchQuery("nationDistribution.property",searchData.getAudienceRegionMore()));
            regionQuery.must(QueryBuilders.matchQuery("nationDistribution.rank",1));
            boolQueryBuilder.must(QueryBuilders.nestedQuery("nationDistribution",regionQuery, ScoreMode.Total));
        }
        //粉丝最多的语言
        if(!StringUtils.isEmpty(searchData.getAudienceLanguageMore())){
            BoolQueryBuilder languageQuery = new BoolQueryBuilder();
            languageQuery.must(QueryBuilders.matchQuery("languageDistribution.property",searchData.getAudienceLanguageMore()));
            languageQuery.must(QueryBuilders.matchQuery("languageDistribution.rank",1));
            boolQueryBuilder.must(QueryBuilders.nestedQuery("languageDistribution",languageQuery, ScoreMode.Total));
        }
        //粉丝最多的性别
        if(searchData.getAudienceGenderMore() > 0 && searchData.getAudienceGenderPercent() == 0){
            BoolQueryBuilder genderQuery = new BoolQueryBuilder();
            genderQuery.must(QueryBuilders.matchQuery("genderDistribution.property",audienceGenders[searchData.getAudienceGenderMore()-1]));
            genderQuery.must(QueryBuilders.matchQuery("genderDistribution.rank",1));
            boolQueryBuilder.must(QueryBuilders.nestedQuery("genderDistribution",genderQuery, ScoreMode.Total));
        }
        //粉丝最多的年龄
        if(searchData.getAudienceAgeMore()> 0&& searchData.getAudienceAgePercent() == 0){
            BoolQueryBuilder ageQuery = new BoolQueryBuilder();
            ageQuery.must(QueryBuilders.matchQuery("ageDistribution.property",ages.get(searchData.getAudienceAgeMore()-1).getGenerationName()));
            ageQuery.must(QueryBuilders.matchQuery("ageDistribution.rank",1));
            boolQueryBuilder.must(QueryBuilders.nestedQuery("ageDistribution",ageQuery, ScoreMode.Total));
        }

        //是否商业
        switch (searchData.getIsBusiness()){
            case 1:
                boolQueryBuilder.must(QueryBuilders.matchQuery("isBusiness",true));
                break;
            case 2:
                boolQueryBuilder.must(QueryBuilders.matchQuery("isBusiness",false));
                break;
        }

        //粉丝性别自定义查询
        if(searchData.getAudienceGenderMore() > 0 && searchData.getAudienceGenderPercent() > 0){
            BoolQueryBuilder genderQuery = new BoolQueryBuilder();
            genderQuery.must(QueryBuilders.matchQuery("genderDistribution.property",audienceGenders[searchData.getAudienceGenderMore()-1]));
            genderQuery.must(QueryBuilders.rangeQuery("genderDistribution.value").gt(searchData.getAudienceGenderPercent()/100));
            boolQueryBuilder.must(QueryBuilders.nestedQuery("genderDistribution",genderQuery, ScoreMode.Total));
        }

        if(searchData.getAudienceAgeMore() > 0 && searchData.getAudienceAgePercent() > 0){
            BoolQueryBuilder ageQuery = new BoolQueryBuilder();
            ageQuery.must(QueryBuilders.matchQuery("ageDistribution.property",ages.get(searchData.getAudienceAgeMore()-1).getGenerationName()));
            ageQuery.must(QueryBuilders.rangeQuery("ageDistribution.value").gt(searchData.getAudienceAgePercent()/100));
            boolQueryBuilder.must(QueryBuilders.nestedQuery("ageDistribution",ageQuery, ScoreMode.Total));
        }

        String sort = "followerCount";

        switch (searchData.getSort()){
            case 1:
                sort = "engagementRate";
                break;
            case 2:
                sort = "realFollowerCount";
                break;
            case 3:
                sort = "followerGrowth";
                break;
            case 4:
                sort = "brandMediaEr";
                break;
            case 5:
                sort = "adTec";
                break;
            case 6:
                sort = "adCount";
                break;
            case 7:
                sort = "avgLike";
                break;
            case 8:
                sort = "avgReviews";
                break;
            default:
                break;
        }
        return RestClientHelper.page(InsBlogger.class,ESUtil.INS_BLOGGER_INDEX,boolQueryBuilder,searchData.getPage(),searchData.getPageSize(),BLOGGER_TOTAL_SIZE,sort,SortOrder.DESC);
    }


    /**
     * 根据uid 近30天账户趋势
     * @param uid
     * @return
     */
    public InsUserTrendResponse getUserTrend(long uid,int dayType){
        InsUserTrendResponse insUserTrendResponse = new InsUserTrendResponse();
        // 获取近30天打点趋势
        int dateCode = Integer.parseInt(DateTimeUtils.millsecond2DateStr(System.currentTimeMillis() / 1000 -
                DAY_TYPE[dayType] * 24 * 3600,"yyyyMMdd"));
        List<InsMarkBloggerDay> insMarkBloggerDayList = insMarkBloggerDayRepository.findMarkInfoByDateCodeAndUid(dateCode,uid);
        if(insMarkBloggerDayList != null && !insMarkBloggerDayList.isEmpty()){
            List<Long> follower = new ArrayList<>(insMarkBloggerDayList.size());
            List<Integer> followerGrow = new ArrayList<>(insMarkBloggerDayList.size());
            List<Integer> post = new ArrayList<>(insMarkBloggerDayList.size());
            List<Integer> postGrow = new ArrayList<>(insMarkBloggerDayList.size());
            List<Integer> dateTime = new ArrayList<>(insMarkBloggerDayList.size());
            for(InsMarkBloggerDay insMarkBloggerDay: insMarkBloggerDayList){
                if(insMarkBloggerDay != null){
                    follower.add(insMarkBloggerDay.getFollowerCount());
                    followerGrow.add(insMarkBloggerDay.getFollowerGrow());
                    post.add(insMarkBloggerDay.getMediaCount());
                    postGrow.add(insMarkBloggerDay.getMediaGrow());
                    dateTime.add(insMarkBloggerDay.getDatecode());
                }
            }
            insUserTrendResponse.setFollower(follower);
            insUserTrendResponse.setFollowerGrow(followerGrow);
            insUserTrendResponse.setPost(post);
            insUserTrendResponse.setPostGrow(postGrow);
            insUserTrendResponse.setDateTime(dateTime);
        }

        val opt = insBloggerRepository.findSaneCfsFollowerGrowthByUid(uid);
        if(opt.isPresent()){
            InsBloggerCfsData insBloggerCfsData = opt.get();
            if(insBloggerCfsData.getExceed() != null){
                insUserTrendResponse.setExceed(insBloggerCfsData.getExceed() >= 100 ? 99.9 : insBloggerCfsData.getExceed());
            }
            if(insBloggerCfsData.getSameCfsRate() != null){
                insUserTrendResponse.setSameFollowerSizeGrowRate(insBloggerCfsData.getSameCfsRate());
            }
            if(insBloggerCfsData.getRate() != null){
                insUserTrendResponse.setGrowRate(insBloggerCfsData.getRate());
                if(insBloggerCfsData.getRate() != null && insBloggerCfsData.getRate() == 0){
                    insUserTrendResponse.setExceed(0);
                }
            }
        }
        return insUserTrendResponse;
    }

    /**
     * 根据uid 获取账户质量得分信息
     * @param uid
     * @return
     */
    public InsUserGoalResponse userGoal(long uid){
        InsUserGoalResponse insUserGoalResponse = new InsUserGoalResponse();;
        val opt = insBloggerRepository.findUserGoalByUid(uid);
        if(opt.isPresent()){
            InsUserGoal insUserGoal = opt.get();
            if(insUserGoal.getAmer() == null || insUserGoal.getAmer() == 0.0){
                insUserGoal.setAdMediaEr(0.0);
                insUserGoal.setAdsPerformance(5);
            }
            if(insUserGoal.getFgr() == null || insUserGoal.getFgr() == 0.0){
                insUserGoal.setFollowerGrowth(5);
                insUserGoal.setFollowerGrowthRate(0.0);
            }
            if(insUserGoal.getRfr() == null || insUserGoal.getRfr() == 0.0){
                insUserGoal.setRealFollower(5);
                insUserGoal.setRealFollowerRate(0.0);
            }
            if(insUserGoal.getMer() == null || insUserGoal.getMer() == 0.0){
                insUserGoal.setMediaEr(0.0);
                insUserGoal.setAvgEr(5);
            }
            insUserGoalResponse.setFollowerGrowth(insUserGoal.getFollowerGrowth());
            insUserGoalResponse.setAvgEr(insUserGoal.getAvgEr());
            insUserGoalResponse.setRealFollower(insUserGoal.getRealFollower());
            insUserGoalResponse.setAdsPerformance(insUserGoal.getAdsPerformance());

            insUserGoalResponse.setFollowerGrowthRate(insUserGoal.getFollowerGrowthRate());
            insUserGoalResponse.setMediaEr(insUserGoal.getMediaEr());
            insUserGoalResponse.setRealFollowerRate(insUserGoal.getRealFollowerRate());
            insUserGoalResponse.setAdMediaEr(insUserGoal.getAdMediaEr());
        }
        return insUserGoalResponse;
    }

    /**
     *
     * @param username
     * @return
     */
    public InsBloggerBaseInfo getUserInfo(String username){
        val insBloggerSimple = insBloggerRepository.findInsBloggerInfoByUid(username);
        if(insBloggerSimple.isEmpty()){
            return new InsBloggerBaseInfo();
        }
        return insBloggerSimple.get();
    }

    /**
     * 根据 uid 获取排名信息
     * @param uid
     * @return
     */
    public InsBloggerRankResponse getUserRank(long uid){
        InsBloggerRankResponse insBloggerRankResponse = new InsBloggerRankResponse();
        val insBloggerRanks = insBloggerRepository.findInsBloggerRankByUid(uid);
        if(!insBloggerRanks.isEmpty()){
            for(InsBloggerRank insBloggerRank : insBloggerRanks){
                if(insBloggerRank != null){
                    if (StringUtils.isEmpty(insBloggerRank.getCategoryName())){
                        if(StringUtils.isEmpty(insBloggerRank.getNation())){
                            insBloggerRankResponse.setWorldRank(insBloggerRank.getRank());
                        }else{
                            insBloggerRankResponse.setNation(insBloggerRank.getNation());
                            insBloggerRankResponse.setNationRank(insBloggerRank.getRank());
                        }
                    }else {
                        if(StringUtils.isEmpty(insBloggerRank.getNation())){
                            insBloggerRankResponse.setCategoryName(insBloggerRank.getCategoryName());
                            insBloggerRankResponse.setCategoryRank(insBloggerRank.getRank());
                        }
                    }
                }
            }
        }
        return insBloggerRankResponse;
    }

    /**
     * 标记商品的帖子统计信息
     * @param uid
     * @param dayType
     * @return
     */
    public InsBloggerProductMediaSt getProductMediaSt(long uid, int dayType){
        return insBloggerRepository.getMediaStForTagProductByUid(uid,DateUtil.offsetDay(new Date(),-DAY_TYPE[dayType]).getTime()/1000,DateUtil.currentSeconds());
    }

    /**
     * 标记该博主的帖子统计信息
     * @param uid
     * @return
     */
    public TaggedMediaCountResp getTaggerBloggerCountByUid(long uid){
        return insBloggerRepository.findTaggerBloggerCountByUid(uid,System.currentTimeMillis() / 1000 - insConfig.getLatestDays() * 24 * 3600,System.currentTimeMillis() / 1000);
    }

    /**
     * 标记该博主的博主分类统计
     * @param uid
     * @return
     */
    public List<InsBloggerCategoryStatistics> getCountTaggerCategory(long uid){

        List<InsBloggerCategoryStatistics> st = insBloggerRepository.findCountTaggerCategory(uid,System.currentTimeMillis() / 1000 - insConfig.getLatestDays() * 24 * 3600,System.currentTimeMillis() / 1000);
        int allCount = 0;

        st.removeIf(i -> io.micrometer.core.instrument.util.StringUtils.isEmpty(i.getCategory()));
        for (InsBloggerCategoryStatistics insBloggerCategoryStatistics : st) {
            allCount +=insBloggerCategoryStatistics.getCount();
        }
        if(allCount > 0){
            InsBloggerCategoryStatistics insBloggerCategoryStatistics = new InsBloggerCategoryStatistics();
            insBloggerCategoryStatistics.setCategory("ALL");
            insBloggerCategoryStatistics.setCount(allCount);
            st.add(0,insBloggerCategoryStatistics);
        }
        return st;
    }

    /**
     * 标记该博主的博主分页信息
     * @param insTaggerBloggerReq
     * @return
     */
    public Page<InsTaggerBloggerResp> getTaggerBloggerPage(InsTaggerBloggerReq insTaggerBloggerReq){
        return insBloggerRepository.findTaggerBloggerPage(insTaggerBloggerReq,System.currentTimeMillis() / 1000 - insConfig.getLatestDays() * 24 * 3600,System.currentTimeMillis() / 1000);
    }
}
